/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "Config.h"
#include "Console.h"
#include "Launcher.h"

#include <algorithm>

/////////////////////////////////////////////////////////////////////////////
//
// ConfigurateGLX
//

void ConfigurateGLX( )
{
	bool AutoClickPlayButton = true;
	bool ShowGLXWindow = true;
	bool StayAfterLaunch = true;
	DWORD PriorityClass = LAUNCHER_PRIORITY_CLASS_LOW;
	DWORD AffinityMask = LAUNCHER_AFFINITY_MASK_CPU_1;
	std::string  GameLauncherPath = "C:\\Nexon\\Maplestory\\GameLauncher.exe";

	Config ConfigurationFile( Util::GetCurrentProcessDirectory( ) + "GLX.glxcfg" );
	if( ConfigurationFile.IsLoaded )
	{
		GameLauncherPath = ConfigurationFile.GetKeywordValue( "GameLauncherPath" );

		if( ConfigurationFile.GetKeywordValue( "AutoClickPlayButton" ) == "yes" )
			AutoClickPlayButton = true;
		else
			AutoClickPlayButton = false;

		if( ConfigurationFile.GetKeywordValue( "ShowGLXWindow" ) == "yes" )
			ShowGLXWindow = true;
		else
			ShowGLXWindow = false;

		if( ConfigurationFile.GetKeywordValue( "StayAfterLaunch" ) == "yes" )
			StayAfterLaunch = true;
		else
			StayAfterLaunch = false;
	
		if( ConfigurationFile.GetKeywordValue( "PriorityClass" ) == "realtime" )
			PriorityClass = LAUNCHER_PRIORITY_CLASS_REALTIME;
		else if( ConfigurationFile.GetKeywordValue( "PriorityClass" ) == "high" )
			PriorityClass = LAUNCHER_PRIORITY_CLASS_HIGH;
		else if( ConfigurationFile.GetKeywordValue( "PriorityClass" ) == "abovenormal" )
			PriorityClass = LAUNCHER_PRIORITY_CLASS_ABOVE_NORMAL;
		else if( ConfigurationFile.GetKeywordValue( "PriorityClass" ) == "normal" )
			PriorityClass = LAUNCHER_PRIORITY_CLASS_NORMAL;
		else if( ConfigurationFile.GetKeywordValue( "PriorityClass" ) == "belownormal" )
			PriorityClass = LAUNCHER_PRIORITY_CLASS_BELOW_NORMAL;
		else
			PriorityClass = LAUNCHER_PRIORITY_CLASS_LOW;

		if( ConfigurationFile.GetKeywordValue( "AffinityMask" ) == "all" )
			AffinityMask = LAUNCHER_AFFINITY_MASK_CPU_ALL;
		else if( ConfigurationFile.GetKeywordValue( "AffinityMask" ) == "0" )
			AffinityMask = LAUNCHER_AFFINITY_MASK_CPU_0;
		else if( ConfigurationFile.GetKeywordValue( "AffinityMask" ) == "1" )
			AffinityMask = LAUNCHER_AFFINITY_MASK_CPU_1;
	}
	
	Console::ShowWindow( ShowGLXWindow );

	if( !Launcher::Launch( GameLauncherPath,
						   PriorityClass,
						   AffinityMask,
						   AutoClickPlayButton ) )
		if( StayAfterLaunch )
			Console::Quit( CONSOLE_QUIT_REASON_FAILED );
		else
			Console::Quit( CONSOLE_QUIT );
	else
		if( StayAfterLaunch )
			Console::Quit( CONSOLE_QUIT_REASON_SUCCEEDED );
		else
			Console::Quit( CONSOLE_QUIT );
}

/////////////////////////////////////////////////////////////////////////////
//
// Config Class
//

Config::Config( __in const std::string &ConfigFilePath )
{
	Console::PrintProgressInfo( "checking configuration file extension" );

	int ExtensionDotPos = ConfigFilePath.find_last_of( '.' ) + 1 ;
	if( ConfigFilePath.substr( ExtensionDotPos, ConfigFilePath.length( ) - ExtensionDotPos ) != "glxcfg" )
		Console::PrintProgressResult( CONSOLE_PROGRESS_RESULT_FAILED_ERROR, "invalid file extension" );
	else
	{
		Console::PrintProgressResult( CONSOLE_PROGRESS_RESULT_SUCCEEDED );
		this->Path = ConfigFilePath.c_str( );
		Extract( );
	}
}

Config::~Config( ) {
}

void Config::CleanUpLine( __inout std::string &Line ) const
{
	Line.erase( remove( Line.begin( ), Line.end( ), (const char)0x20 ), Line.end( ) );
	Line.erase( remove( Line.begin( ), Line.end( ), (const char)0x09 ), Line.end( ) );
	Line.erase( remove( Line.begin( ), Line.end( ), (const char)0x0A ), Line.end( ) );
	Line.erase( remove( Line.begin( ), Line.end( ), (const char)0x0D ), Line.end( ) );

	if( Line.find( '/' ) != Line.npos )
		Line.erase( Line.find( '/' ) );

	std::transform( Line.begin( ), Line.end( ), Line.begin( ), tolower );
}

bool Config::IsValidLine( __inout std::string &Line ) const
{
	if( Line.length( ) <= 0 )
		return false;
	else if( Line[ 0 ] == '/' )
		return false;
	else if( Line.find( '=' ) == -1 )
		return false;
	else if( Line[ 0 ] == '=' )
		return false;
	else if( Line[ Line.length( ) - 1 ] == '=' )
		return false;
	else
		return true;
}

void Config::Extract( )
{
	Console::PrintProgressInfo( "attempting to load GLX configuration file" );

	std::ifstream ConfigFile;
	ConfigFile.open( Config::Path.c_str( ) );

	if( ConfigFile.fail( ) ) {
		Console::PrintProgressResult( CONSOLE_PROGRESS_RESULT_FAILED );
		IsLoaded = false;
	}
	else
	{
		IsLoaded = true;
		std::string Line;
		while( !ConfigFile.eof( ) )
		{
			getline( ConfigFile, Line );
			CleanUpLine( Line );

			int EqualCharPos = -1;

			if( IsValidLine( Line ) )
			{
				EqualCharPos = Line.find( '=' );
				Contents.insert( std::pair< std::string, std::string >(
					Line.substr( 0, EqualCharPos ), Line.substr( EqualCharPos + 1, Line.length( ) - EqualCharPos ) ) );
			}
		}
		Console::PrintProgressResult( CONSOLE_PROGRESS_RESULT_SUCCEEDED );
		ConfigFile.close( );
	}
}

bool Config::KeywordExists( __in std::string Keyword ) const
{
	std::transform( Keyword.begin( ), Keyword.end( ), Keyword.begin( ), tolower );

	return Contents.find( Keyword ) != Contents.end( );
}

std::string Config::GetKeywordValue( __in std::string Keyword ) const
{
	std::transform( Keyword.begin( ), Keyword.end( ), Keyword.begin( ), tolower );

	if( KeywordExists( Keyword ) )
		return Contents.find( Keyword )->second;
	return "";
}